package com.newlink.building.common_base.utils

import android.content.Context
import android.content.SharedPreferences
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import com.newlink.building.common_base.base.BaseApplication

/**
 * Optimized Preference Helper for batch operations
 * Reduces disk I/O by grouping related preferences
 */
object PreferenceHelper {

    private const val PREF_NAME = "app_preferences"
    private const val USER_PREFS_KEY = "user_preferences"
    private const val APP_SETTINGS_KEY = "app_settings"
    private const val NETWORK_CONFIG_KEY = "network_config"

    private val prefs: SharedPreferences by lazy {
        BaseApplication.context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE)
    }

    private val gson = Gson()

    /**
     * User related preferences grouped together
     */
    data class UserPreferences(
        val accessToken: String = "",
        val userId: Long = 0L,
        val phoneNumber: String = "",
        val emailAccount: String = "",
        val sipAccount: String = "",
        val pwdSaved: String = "",
        val isSaveAccountAndPwd: Boolean = true,
        val agoraId: Int = 0,
        val agoraAppId: String = "",
        val projectId: String = "",
        val countryCode: String = "",
        val isLogin: Boolean = false
    )

    /**
     * App settings grouped together
     */
    data class AppSettings(
        val bluetoothOpenDoor: Boolean = false,
        val useBluetooth: Boolean = false,
        val lastBleAddr: String = "",
        val maxUserCount: Int = 4,
        val shakeLevel: Int = 2,
        val serverType: Int = 0,
        val hasNetwork: Boolean = true,
        val hasKcpNetwork: Boolean = true
    )

    /**
     * Network configuration grouped together
     */
    data class NetworkConfig(
        val apiEnv: Int = -1,
        val apiEnvUrl: String = "",
        val apiEnvUrlCustom: String = "",
        val flsServer: String = "",
        val mqttHost: String = "",
        val mqttUsername: String = "",
        val mqttPassword: String = "",
        val mqttSSL: Boolean = false,
        val kcpConnectId: Int = -1,
        val kcpDestDeviceId: String = "",
        val kcpUserId: String = ""
    )

    /**
     * Save user preferences as a batch
     */
    fun saveUserPreferences(userPrefs: UserPreferences) {
        prefs.edit().putString(USER_PREFS_KEY, gson.toJson(userPrefs)).apply()
    }

    /**
     * Get user preferences
     */
    fun getUserPreferences(): UserPreferences {
        val json = prefs.getString(USER_PREFS_KEY, null)
        return if (json != null) {
            gson.fromJson(json, UserPreferences::class.java)
        } else {
            UserPreferences()
        }
    }

    /**
     * Save app settings as a batch
     */
    fun saveAppSettings(settings: AppSettings) {
        prefs.edit().putString(APP_SETTINGS_KEY, gson.toJson(settings)).apply()
    }

    /**
     * Get app settings
     */
    fun getAppSettings(): AppSettings {
        val json = prefs.getString(APP_SETTINGS_KEY, null)
        return if (json != null) {
            gson.fromJson(json, AppSettings::class.java)
        } else {
            AppSettings()
        }
    }

    /**
     * Save network configuration as a batch
     */
    fun saveNetworkConfig(config: NetworkConfig) {
        prefs.edit().putString(NETWORK_CONFIG_KEY, gson.toJson(config)).apply()
    }

    /**
     * Get network configuration
     */
    fun getNetworkConfig(): NetworkConfig {
        val json = prefs.getString(NETWORK_CONFIG_KEY, null)
        return if (json != null) {
            gson.fromJson(json, NetworkConfig::class.java)
        } else {
            NetworkConfig()
        }
    }

    /**
     * Update specific user preference field
     */
    inline fun updateUserPreferences(crossinline update: (UserPreferences) -> UserPreferences) {
        val current = getUserPreferences()
        val updated = update(current)
        saveUserPreferences(updated)
    }

    /**
     * Update specific app setting field
     */
    inline fun updateAppSettings(crossinline update: (AppSettings) -> AppSettings) {
        val current = getAppSettings()
        val updated = update(current)
        saveAppSettings(updated)
    }

    /**
     * Update specific network config field
     */
    inline fun updateNetworkConfig(crossinline update: (NetworkConfig) -> NetworkConfig) {
        val current = getNetworkConfig()
        val updated = update(current)
        saveNetworkConfig(updated)
    }

    /**
     * Clear all preferences
     */
    fun clearAll() {
        prefs.edit().clear().apply()
    }

    /**
     * Migrate from old individual preferences to batch preferences
     * This should be called once during app upgrade
     */
    fun migrateFromOldPreferences(oldPrefs: SharedPreferences) {
        // Get old values
        val userPrefs = UserPreferences(
            accessToken = oldPrefs.getString("access_token", "") ?: "",
            userId = oldPrefs.getLong("user_id", 0L),
            phoneNumber = oldPrefs.getString("phone_number", "") ?: "",
            emailAccount = oldPrefs.getString("email_account", "") ?: "",
            sipAccount = oldPrefs.getString("sip_account", "") ?: "",
            pwdSaved = oldPrefs.getString("password_saved", "") ?: "",
            isSaveAccountAndPwd = oldPrefs.getBoolean("save_account_pwd", true),
            agoraId = oldPrefs.getInt("agora_id", 0),
            agoraAppId = oldPrefs.getString("agora_app_id", "") ?: "",
            projectId = oldPrefs.getString("project_id", "") ?: "",
            countryCode = oldPrefs.getString("country_code", "") ?: "",
            isLogin = oldPrefs.getBoolean("is_login", false)
        )

        val appSettings = AppSettings(
            bluetoothOpenDoor = oldPrefs.getBoolean("bluetooth_open_door", false),
            useBluetooth = oldPrefs.getBoolean("use_bluetooth", false),
            lastBleAddr = oldPrefs.getString("last_ble_addr", "") ?: "",
            maxUserCount = oldPrefs.getInt("max_user_count", 4),
            shakeLevel = oldPrefs.getInt("shake_level", 2),
            serverType = oldPrefs.getInt("server_type", 0),
            hasNetwork = oldPrefs.getBoolean("has_network", true),
            hasKcpNetwork = oldPrefs.getBoolean("has_kcp_network", true)
        )

        // Save batched preferences
        saveUserPreferences(userPrefs)
        saveAppSettings(appSettings)

        // Mark migration complete
        prefs.edit().putBoolean("migration_complete", true).apply()
    }
}